package com.mp.approvalreq.util;

import com.alibaba.fastjson.JSONObject;
import com.mp.approvalreq.entity.*;
import com.mp.user.entity.User;
import com.mp.user.service.UserServicePrx;
import com.plusmoney.util.Utils;
import com.qq.tars.client.util.ServantUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

public class ModifyUtils {

    public static List<ApprovalModify> getUpdateModifies(Template oldTemplate, Template template) throws Throwable {
        List<ApprovalModify> list = new ArrayList<>();
        User user = template.getUser();
        ObjectUtils.initInteger(oldTemplate);
        ObjectUtils.initInteger(template);
        List<TemplateComponent> oldComponent = JSONObject.parseArray(oldTemplate.getTemplateComponent(), TemplateComponent.class);
        List<TemplateComponent> component = JSONObject.parseArray(template.getTemplateComponent(), TemplateComponent.class);

        if (template.getDefaultType() == Template.APPEND_SIGN || template.getDefaultType() == Template.COMPENSATORY_LEAVE) {
            String typeDesc = template.getDefaultType() == Template.APPEND_SIGN ? "补打卡" : "补假";
            if (!Objects.equals(oldTemplate.getIsMaxTime(), template.getIsMaxTime())) {
                ApprovalModify modify = new ApprovalModify(template);
                if (template.getIsMaxTime() > oldTemplate.getIsMaxTime()) {
                    modify.setTitle(getModifyDesc("%s开启「%s」申请" + typeDesc + "次数上限", user.getContactName(), template.getTemplateName()));
                    modify.setDetail("申请" + typeDesc + "次数上限 : " + template.getMaxTimePermonth());
                } else {
                    modify.setTitle(getModifyDesc("%s关闭「%s」申请次数上限设置", user.getContactName(), template.getTemplateName()));
                }
                list.add(modify);
            } else if (!Objects.equals(oldTemplate.getMaxTimePermonth(), template.getMaxTimePermonth())) {
                ApprovalModify modify = new ApprovalModify(template);
                modify.setTitle(getModifyDesc("%s修改「%s」申请" + typeDesc + "次数上限", user.getContactName(), template.getTemplateName()));
                modify.setDetail(getModifyDesc("%s → %s", oldTemplate.getMaxTimePermonth(), template.getMaxTimePermonth()));
                list.add(modify);
            }

            if (!Objects.equals(oldTemplate.getContentTimeLimit(), template.getContentTimeLimit())) {
                ApprovalModify modify = new ApprovalModify(template);
                String typeFormat = template.getDefaultType() == Template.APPEND_SIGN ? "忘打卡后 : %s 天内" : "忘请假后 : %s 天内";
                if (oldTemplate.getContentTimeLimit() == 0) {
                    modify.setTitle(getModifyDesc("%s开启「%s」申请时间限制", user.getContactName(), template.getTemplateName()));
                    modify.setDetail(String.format(typeFormat, template.getContentTimeLimit()));
                } else if (template.getContentTimeLimit() == 0) {
                    modify.setTitle(getModifyDesc("%s关闭「%s」申请时间限制", user.getContactName(), template.getTemplateName()));
                } else {
                    modify.setTitle(getModifyDesc("%s修改「%s」申请时间限制", user.getContactName(), template.getTemplateName()));
                    modify.setDetail(String.format(typeFormat, String.format("%d → %d", oldTemplate.getContentTimeLimit(), template.getContentTimeLimit())));
                }
                list.add(modify);
            }
        }

        if (template.getDefaultType() == Template.OUTDOOR) {
            if (!Objects.equals(template.getOutSignOffset(), oldTemplate.getOutSignOffset())) {
                ApprovalModify modify = new ApprovalModify(template);
                modify.setTitle(getModifyDesc("%s修改「%s」外出打卡允许偏差", user.getContactName(), template.getTemplateName()));
                modify.setDetail(getModifyDesc("%s → %s", getDistance(oldTemplate.getOutSignOffset()), getDistance(template.getOutSignOffset())));
                list.add(modify);
            }
            TemplateComponent before = ComponentUtils.getComponentByNumber(oldComponent, 3);
            TemplateComponent after = ComponentUtils.getComponentByNumber(component, 3);
            if (Utils.isNotNull(before) && Utils.isNotNull(after) && !Objects.equals(before.getNeed(), after.getNeed())) {
                ApprovalModify modify = new ApprovalModify(template);
                if (after.getNeed() > before.getNeed()) {
                    modify.setTitle(getModifyDesc("%s开启「%s」申请外出时必须填写外出地点", user.getContactName(), template.getTemplateName()));
                } else {
                    modify.setTitle(getModifyDesc("%s关闭「%s」申请外出时必须填写外出地点", user.getContactName(), template.getTemplateName()));
                }
                list.add(modify);
            }
        }

        if (template.getDefaultType() == Template.BUSINESS_TRIP) {
            TemplateComponent before = ComponentUtils.getComponentByNumber(oldComponent, 3);
            TemplateComponent after = ComponentUtils.getComponentByNumber(component, 3);
            if (Utils.isNotNull(before) && Utils.isNotNull(after) && !Objects.equals(before.getNeed(), after.getNeed())) {
                ApprovalModify modify = new ApprovalModify(template);
                if (after.getNeed() > before.getNeed()) {
                    modify.setTitle(getModifyDesc("%s开启「%s」申请出差时必须填写目的地", user.getContactName(), template.getTemplateName()));
                } else {
                    modify.setTitle(getModifyDesc("%s关闭「%s」申请出差时必须填写目的地", user.getContactName(), template.getTemplateName()));
                }
                list.add(modify);
            }
        }

        if (template.getDefaultType() == Template.EXPENSES || template.getDefaultType() == Template.PURCHASE) {
            TemplateComponent before = ComponentUtils.getComponentByNumber(oldComponent, 4);
            TemplateComponent after = ComponentUtils.getComponentByNumber(component, 4);
            if (Utils.isNotNull(before) && Utils.isNotNull(after) && !Objects.equals(before.getNeed(), after.getNeed())) {
                ApprovalModify modify = new ApprovalModify(template);
                if (after.getNeed() > before.getNeed()) {
                    modify.setTitle(getModifyDesc("%s开启「%s」" + getAttachmentDesc(template), user.getContactName(), template.getTemplateName()));
                } else {
                    modify.setTitle(getModifyDesc("%s关闭「%s」" + getAttachmentDesc(template), user.getContactName(), template.getTemplateName()));
                }
                list.add(modify);
            }
        }


        int oldAttachment = ComponentUtils.countByContentType(oldComponent, ContentType.ATTACHMENT);
        int newAttachment = ComponentUtils.countByContentType(component, ContentType.ATTACHMENT);
        if (oldAttachment != newAttachment) {
            ApprovalModify modify = new ApprovalModify(template);
            if (newAttachment > oldAttachment) {
                modify.setTitle(getModifyDesc("%s开启「%s」" + getAttachmentDesc(template), user.getContactName(), template.getTemplateName()));
            } else {
                modify.setTitle(getModifyDesc("%s关闭「%s」" + getAttachmentDesc(template), user.getContactName(), template.getTemplateName()));
            }
            list.add(modify);
        }
        if (!Objects.equals(oldTemplate.getTemplateName(), template.getTemplateName())) {
            ApprovalModify modify = new ApprovalModify(template);
            modify.setTitle(getModifyDesc("%s修改「%s」模版名称", user.getContactName(), template.getTemplateName()));
            modify.setDetail(getModifyDesc("%s → %s", oldTemplate.getTemplateName(), template.getTemplateName()));
            list.add(modify);
        }
        if (!Objects.equals(oldTemplate.getTemplateTips(), template.getTemplateTips())) {
            ApprovalModify modify = new ApprovalModify(template);
            modify.setTitle(getModifyDesc("%s修改「%s」介绍", user.getContactName(), template.getTemplateName()));
            list.add(modify);
        }
        if (!Objects.equals(oldTemplate.getRelaPeopleNum(), template.getRelaPeopleNum())) {
            ApprovalModify modify = new ApprovalModify(template);
            if (oldTemplate.getRelaPeopleNum() <= 0 && template.getRelaPeopleNum() > 0) {
                modify.setTitle(getModifyDesc("%s开启「%s」审批参与人", user.getContactName(), template.getTemplateName()));
                list.add(modify);
            } else if (oldTemplate.getRelaPeopleNum() > 0 && template.getRelaPeopleNum() <= 0) {
                modify.setTitle(getModifyDesc("%s关闭「%s」审批参与人", user.getContactName(), template.getTemplateName()));
                list.add(modify);
            }
        }
        if (!Objects.equals(oldTemplate.getRelaRequestNum(), template.getRelaRequestNum())) {
            ApprovalModify modify = new ApprovalModify(template);
            if (oldTemplate.getRelaRequestNum() <= 0 && template.getRelaRequestNum() > 0) {
                modify.setTitle(getModifyDesc("%s开启「%s」关联审批", user.getContactName(), template.getTemplateName()));
                list.add(modify);
            } else if (oldTemplate.getRelaRequestNum() > 0 && template.getRelaRequestNum() <= 0) {
                modify.setTitle(getModifyDesc("%s关闭「%s」关联审批", user.getContactName(), template.getTemplateName()));
                list.add(modify);
            }
        }
        int oldRelatedRequest = ComponentUtils.countByContentType(oldComponent, ContentType.RELATED_APPROVAL);
        int newRelatedRequest = ComponentUtils.countByContentType(component, ContentType.RELATED_APPROVAL);
        if (oldRelatedRequest != newRelatedRequest) {
            ApprovalModify modify = new ApprovalModify(template);
            if (newRelatedRequest > oldRelatedRequest) {
                modify.setTitle(getModifyDesc("%s开启「%s」关联审批", user.getContactName(), template.getTemplateName()));
            } else {
                modify.setTitle(getModifyDesc("%s关闭「%s」关联审批", user.getContactName(), template.getTemplateName()));
            }
            list.add(modify);
        }

        int oldRelatedTask = ComponentUtils.countByContentType(oldComponent, ContentType.RELATED_TASK);
        int newRelatedTask = ComponentUtils.countByContentType(component, ContentType.RELATED_TASK);
        if (oldRelatedTask != newRelatedTask) {
            ApprovalModify modify = new ApprovalModify(template);
            if (newRelatedTask > oldRelatedTask) {
                modify.setTitle(getModifyDesc("%s开启「%s」关联任务", user.getContactName(), template.getTemplateName()));
            } else {
                modify.setTitle(getModifyDesc("%s关闭「%s」关联任务", user.getContactName(), template.getTemplateName()));
            }
            list.add(modify);
        }

        int oldCrm = ComponentUtils.countByContentType(oldComponent, ContentType.RELATED_CLIENT);
        int newCrm = ComponentUtils.countByContentType(component, ContentType.RELATED_CLIENT);
        if (oldCrm != newCrm) {
            ApprovalModify modify = new ApprovalModify(template);
            if (newRelatedTask > oldRelatedTask) {
                modify.setTitle(getModifyDesc("%s开启「%s」关联客户", user.getContactName(), template.getTemplateName()));
            } else {
                modify.setTitle(getModifyDesc("%s关闭「%s」关联客户", user.getContactName(), template.getTemplateName()));
            }
            list.add(modify);
        }
        if (!Objects.equals(oldTemplate.getCompanyInfoIdRange(), template.getCompanyInfoIdRange())) {
            ApprovalModify modify = new ApprovalModify(template);
            modify.setTitle(getModifyDesc("%s调整「%s」适用范围", user.getContactName(), template.getTemplateName()));
            list.add(modify);
        }
        if (!Objects.equals(oldTemplate.getCc(), template.getCc())) {
            ApprovalModify modify = new ApprovalModify(template);
            modify.setTitle(getModifyDesc("%s修改「%s」默认抄送人", user.getContactName(), template.getTemplateName()));

            List<String> oldCc = getFlowList(oldTemplate.getCc());
            List<String> newCc = getFlowList(template.getCc());
            Map<String, String> nameMap = getNameMap(oldCc, newCc);
            StringBuilder sb = new StringBuilder();
            if (Utils.isEmpty(oldCc)) {
                sb.append("   ");
            } else {
                for (String str : oldCc) {
                    sb.append(nameMap.get(str));
                    sb.append("、");
                }
            }
            sb.deleteCharAt(sb.length() - 1);
            sb.append(" → ");
            if (Utils.isEmpty(newCc)) {
                sb.append("   ");
            } else {
                for (String str : newCc) {
                    sb.append(nameMap.get(str));
                    sb.append("、");
                }
            }
            sb.deleteCharAt(sb.length() - 1);
            modify.setDetail(sb.toString());
            list.add(modify);
        }
        if (!Objects.equals(oldTemplate.getIsAllowAddTempCc(), template.getIsAllowAddTempCc())) {
            ApprovalModify modify = new ApprovalModify(template);
            if (oldTemplate.getIsAllowAddTempCc() <= 0 && template.getIsAllowAddTempCc() > 0) {
                modify.setTitle(getModifyDesc("%s开启「%s」临时抄送人", user.getContactName(), template.getTemplateName()));
            } else if (oldTemplate.getIsAllowAddTempCc() > 0 && template.getIsAllowAddTempCc() <= 0) {
                modify.setTitle(getModifyDesc("%s关闭「%s」临时抄送人", user.getContactName(), template.getTemplateName()));
            }
            list.add(modify);
        }
        if (!Objects.equals(oldTemplate.getProxyContactIds(), template.getProxyContactIds())) {
            ApprovalModify modify = new ApprovalModify(template);
            if (StringUtils.isBlank(oldTemplate.getProxyContactIds()) && StringUtils.isNotBlank(template.getProxyContactIds())) {
                modify.setTitle(getModifyDesc("%s开启「%s」允许代他人申请", user.getContactName(), template.getTemplateName()));
            } else if (StringUtils.isBlank(template.getProxyContactIds()) && StringUtils.isNotBlank(oldTemplate.getProxyContactIds())) {
                modify.setTitle(getModifyDesc("%s关闭「%s」允许代他人申请", user.getContactName(), template.getTemplateName()));
            } else {
                modify.setTitle(getModifyDesc("%s修改「%s」允许代他人申请", user.getContactName(), template.getTemplateName()));
            }
            list.add(modify);
        }

        if (!Objects.equals(oldTemplate.getRequestFlow(), template.getRequestFlow())) {
            ApprovalModify modify = new ApprovalModify(template);
            modify.setTitle(getModifyDesc("%s修改「%s」审批流程", user.getContactName(), template.getTemplateName()));
            String before = getFlowDesc(oldTemplate.getRequestFlow());
            String after = getFlowDesc(template.getRequestFlow());
            if (before.equals(after)) {
                // 都是自定义
                List<String> oldFlows = getFlowList(oldTemplate.getRequestFlow());
                List<String> newFlows = getFlowList(template.getRequestFlow());
                List<String> removed = getDiff(oldFlows, newFlows);
                List<String> added = getDiff(newFlows, oldFlows);
                Map<String, String> nameMap = getNameMap(removed, added);
                StringBuilder sb = new StringBuilder();
                if (Utils.isNotEmpty(added)) {
                    sb.append("增加");
                    for (String str : added) {
                        if (!nameMap.containsKey(str)) {
                            continue;
                        }
                        sb.append(nameMap.get(str));
                        sb.append("、");
                    }
                    sb.deleteCharAt(sb.length() - 1);
                    sb.append("为审批人");
                }
                if (Utils.isNotEmpty(removed)) {
                    if (StringUtils.isNotEmpty(sb)) {
                        sb.append("\n");
                    }
                    for (String str : removed) {
                        if (!nameMap.containsKey(str)) {
                            continue;
                        }
                        sb.append(nameMap.get(str));
                        sb.append("、");
                    }
                    if (StringUtils.endsWith(sb, "、")) {
                        sb.deleteCharAt(sb.length() - 1);
                        sb.append("在审批流程被移除");
                    }
                }
                modify.setDetail(sb.toString());
            } else {
                modify.setDetail(getModifyDesc("%s → %s", before, after));
            }
            list.add(modify);
        } else {
            if (Utils.isNotEmpty(template.getConditionFlow())) {
                // 条件审批流
                List<ConditionFlow> oldConditions = oldTemplate.getConditionFlow();
                List<ConditionFlow> newConditions = template.getConditionFlow();
                try {
                    oldConditions.sort((Comparator.comparing(ConditionFlow::getSmallerFactor)));
                    newConditions.sort((Comparator.comparing(ConditionFlow::getSmallerFactor)));
                } catch (Exception e) {
                    // 无须排序
                }

                ConditionFlow oldCondition = oldConditions.get(0);
                ConditionFlow newCondition = newConditions.get(0);

                ApprovalModify modify = new ApprovalModify(template);
                modify.setTitle(getModifyDesc("%s修改「%s」条件流程", user.getContactName(), template.getTemplateName()));
                if (!Objects.equals(oldCondition.getConditionType(), newCondition.getConditionType())) {
                    String before = getConditionDesc(oldCondition.getConditionType());
                    String after = getConditionDesc(newCondition.getConditionType());
                    modify.setDetail(getModifyDesc("%s → %s", before, after));
                } else {
                    if (StringUtils.isNotEmpty(oldCondition.getChooseItems())) {
                        if (!Objects.equals(oldCondition.getChooseItems(), newCondition.getChooseItems())) {
                            String before = ListHelper.list2string(JSONObject.parseArray(oldCondition.getChooseItems()));
                            String after = ListHelper.list2string(JSONObject.parseArray(newCondition.getChooseItems()));
                            modify.setDetail(getModifyDesc("%s → %s", before, after));
                        }
                    } else if (!Objects.equals(oldCondition.getSmallerFactor(), newCondition.getSmallerFactor())
                            || !Objects.equals(oldCondition.getGreaterFactor(), newCondition.getGreaterFactor())) {
                        String before = getConditionFormula(oldCondition);
                        String after = getConditionFormula(newCondition);
                        modify.setDetail(getModifyDesc("%s → %s", before, after));
                    }
                }
                list.add(modify);
            }
        }

        return list;
    }

    private static String getDistance(String outSignOffset) {
        if (Utils.isNull(outSignOffset)) {
            return "1千米";
        }
        int distance = Integer.parseInt(outSignOffset);
        if (distance > 6000000) {
            return "不限制";
        }
        return distance / 1000 + "千米";
    }

    private static String getAttachmentDesc(Template template) {
        switch (template.getDefaultType()) {
            case Template.EXPENSES:
                return "强制上传凭证";
            case Template.PURCHASE:
                return "添加附件";
            default:
                return "相关附件";
        }
    }

    private static String getConditionFormula(ConditionFlow conditionFlow) {
        return conditionFlow.getSmallerFactor()
                + getSymbol(conditionFlow.getLeftSymbol())
                + getConditionDesc(conditionFlow.getConditionType())
                + getSymbol(conditionFlow.getRightSymbol())
                + conditionFlow.getGreaterFactor();
    }

    private static String getSymbol(int leftSymbol) {
        return leftSymbol == 0 ? "<" : "≤";
    }

    private static String getConditionDesc(String conditionType) {
        if ("1".equals(conditionType)) {
            return "金额";
        }
        if ("2".equals(conditionType)) {
            return "时长";
        }
        return "单选项";
    }

    private static Map<String, String> getNameMap(List<String> removed, List<String> added) throws Throwable {
        Map<String, String> map = new HashMap<>();
        Set<Integer> idCollector = new HashSet<>();
        collectIds(removed, idCollector);
        collectIds(added, idCollector);
        if (Utils.isNotEmpty(idCollector)) {
            UserServicePrx userServicePrx = ServantUtils.getObject(UserServicePrx.class);
            List<User> users = userServicePrx.getUserListByContactIds(Utils.collection2string(idCollector));
            for (User user : users) {
                map.put(String.valueOf(user.getContactId()), user.getContactName());
            }
        }
        map.put("SP", "申请人的直接上级");
        map.put("DSP", "申请人的直接副主管");
        map.put("DM", "申请人的间接上级");
        map.put("DDM", "申请人的间接副主管");
        return map;
    }

    private static void collectIds(List<String> removed, Set<Integer> idCollector) {
        if (Utils.isNotEmpty(removed)) {
            for (String str : removed) {
                if (ValidateUtil.isInteger(str)) {
                    idCollector.add(Integer.parseInt(str));
                }
            }
        }
    }

    /**
     * 获取a、b的差集
     *
     * @param a
     * @param b
     * @return
     */
    private static List<String> getDiff(List<String> a, List<String> b) {
        List<String> list = new ArrayList<>(a);
        list.removeAll(b);
        return list;
    }

    private static List<String> getFlowList(String requestFlow) {
        if (StringUtils.isBlank(requestFlow)) {
            return new ArrayList<>();
        }
        String str = requestFlow.replaceAll("\\|\\|", ",").replaceAll("&&", ",");
        return ListHelper.string2StringList(str);
    }

    private static String getModifyDesc(String format, Object one, Object two) {
        return String.format(format, one, two);
    }

    private static String getFlowDesc(String requestFlow) {
        if (RequestFlowType.DEFAULT.equals(requestFlow)) {
            return "默认流程";
        }
        if (RequestFlowType.ALTERNATIVE.equals(requestFlow)) {
            return "灵活审批流程";
        }
        if (RequestFlowType.CONDITION.equals(requestFlow)) {
            return "条件审批流程";
        }
        return "自定义审批流程";
    }
}
